package com.fdb.efp.nls.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fdb.efp.console.service.vo.SCfgParamVO;
import com.fdb.efp.nls.service.facade.queue.NlsProcessRuleService;
import com.fdb.efp.nls.service.vo.NlsApplyInfoVO;
import com.fdb.efp.nls.service.vo.queue.NlsProcessBizVO;
import com.fdb.efp.nls.service.vo.queue.NlsProcessRuleVO;
import com.fdb.basic.framework.core.exception.BizException;
import com.fdb.basic.framework.core.util.DateTool;
import com.fdb.basic.framework.core.util.DateUtility;
import com.fdb.basic.framework.core.util.StringUtil;
import com.fdb.basic.framework.core.util.TimeUtil;
import com.fdb.cdp.pboc.service.facade.*;
import com.fdb.cdp.pboc.service.vo.*;
import com.fdb.efp.nls.service.facade.PrdInfoService;
import com.fdb.efp.nls.service.facade.PrdSoltRuleService;
import com.fdb.efp.nls.service.facade.SCfgParamService;
import com.fdb.efp.nls.service.vo.PrdInfoVO;
import com.fdb.efp.nls.service.vo.PrdSoltRuleVO;
import com.fdb.efp.esb.service.bo.req.ZXCXA01QueryReports;
import com.fdb.efp.esb.service.facade.zx.NewZXService;
import com.fdb.efp.esb.service.vo.zx.ZXVO;
import com.fdb.efp.nls.common.constant.AccountTypeEnum;
import com.fdb.efp.nls.common.constant.AcctStEnum;
import com.fdb.efp.nls.common.constant.PrdAdaptedSoltEnums;
import com.fdb.efp.rule.common.enumeration.Rule;
import com.fdb.efp.rule.service.facade.RuleCallService;
import com.fdb.efp.rule.service.vo.ReqMsZxRuleVo;
import com.fdb.efp.rule.service.vo.ReqRuleVo;
import com.fdb.efp.rule.service.vo.RespRuleVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:马上二代征信规则服务
 * @date:2020年01月21日 下午15:37:41
 * @author:dengqiwen
 */
@Service("MsZXRuleService")
public class MsZXRuleServiceImpl extends SoltServiceImpl {

    private static final Logger log = LoggerFactory.getLogger(MsZXRuleServiceImpl.class);

    @Autowired
    @Qualifier("ruleCallService")
    private RuleCallService ruleService;
    @Autowired
    @Qualifier("nlsProcessRuleService")
    private NlsProcessRuleService nlsProcessRuleService;
    @Autowired
    @Qualifier("prdSoltRuleService")
    private PrdSoltRuleService prdSoltRuleService;
    @Autowired
    @Qualifier("prdInfoService")
    private PrdInfoService prdInfoService;
    @Autowired
    @Qualifier("zxJsonInfoService")
    private ZXJsonInfoService zxJsonInfoService;
    @Autowired
    @Qualifier("zxCXA01Service")
    private NewZXService<ZXCXA01QueryReports> zxCXA01Service;
    @Autowired
    @Qualifier("sCfgParamService")
    private SCfgParamService sCfgParamService;


    @Override
    public  void doExecute(NlsProcessBizVO nlsProcessBizVo, NlsApplyInfoVO nlsApplyInfoVO) throws Exception {
        String applySeq = nlsProcessBizVo.getApplySeq();
        String slotCode = nlsProcessBizVo.getSoltCode();

        try {
            /** 查询申请信息，获得征信查询接口所需的参数 **/
            String appNo = applySeq;
            log.info("开始进行征信规则参数准备,流水号:" + appNo);
            Objects.requireNonNull(nlsApplyInfoVO);
            String cusName = nlsApplyInfoVO.getCusName();
            String certNo = nlsApplyInfoVO.getCertCode();
            String certType = nlsApplyInfoVO.getCertType();
            String authCd = appNo;
            String prdName = nlsApplyInfoVO.getPrdName(); // 产品名称
            String bussinessType = nlsApplyInfoVO.getPrdCode(); // 产品编号
            String authDate = nlsApplyInfoVO.getApplyDate();//授权日期
            String authTime = nlsApplyInfoVO.getApplyTime();//授权时间
            String authTm=DateUtility.formatDateTime19To14(authDate+" "+authTime);
            String date=DateTool.getCurrentDate();
            String StopDate=TimeUtil.addDay(date, 90);
            /** 查询产品获取征信userId */
            String prdId = Objects.requireNonNull(nlsApplyInfoVO.getPrdId());
            PrdInfoVO prdInfoVo = new PrdInfoVO();
            prdInfoVo.setPrdId(prdId);
            prdInfoVo = prdInfoService.queryByPk(prdInfoVo);
            //查询参数
            List<SCfgParamVO> params = sCfgParamService.queryToZx();
            String RprtUsr= null,RprtUsrBlngDept = null,valiDay= null;
            for (SCfgParamVO param : params) {
                if(param.getParamKey().equals("ZX_RprtUsr")){
                    RprtUsr=param.getParamValue();
                    continue;
                }
                if(param.getParamKey().equals("ZX_RprtUsrBlngDept")){
                    RprtUsrBlngDept=param.getParamValue();
                    continue;
                } if(param.getParamKey().equals("ZX_MS_VALID_DAY")){
                    valiDay=param.getParamValue();
                    continue;
                }
            }

            /** 调用征信查询接口 **/
            final String queryAppType = "05",queryReason = "02",queryType = "0",authMd="19",crdtRprtQryMd="1";
            ZXCXA01QueryReports ZXQueryReports=new ZXCXA01QueryReports.Builder().withQryAppTp(queryAppType).withRprtUsr(RprtUsr).withRprtUsrBlngDept(RprtUsrBlngDept)
                    .withCustNm(cusName).withIdentTp(certType).withIdentNo(certNo).withQryRsn(queryReason).withQryTp(queryType)
                    .withAcqrngCustSrc("马上消费金融股份有限公司").withPdNm(prdName).withAuthMd(authMd)
                    .withCrdtRprtQryMd(crdtRprtQryMd)
                    .withAuthTm(authTm).withAuthStrtDt(date).withAuthStopDt(StopDate).build();
            String reportId = null;
            ZXJsonInfoVO queryReportVo = new ZXJsonInfoVO();
            queryReportVo.setCertCode(certNo);
            List<ZXJsonInfoVO> zxInfo = zxJsonInfoService.queryReportId(queryReportVo);
            if(zxInfo.size()>0) {//有征信数据
                String reportTime = zxInfo.get(0).getReportTime();//最新征信报告时间
                reportTime = StringUtils.replace(reportTime, ".", "-");//转换yyyy-MM-dd HH:mm:ss
                log.info("当前用户征信报告日期" + reportTime);
                int day = TimeUtil.compareDates(TimeUtil.addDay(reportTime, Integer.parseInt(valiDay)), DateTool.getCurrentDateTime());
                if(day < 0) {//报告时间大于30天，调用征信接口
                    try {
                        ZXVO zxvoJson = zxCXA01Service.Zxservice(ZXQueryReports,params);
                        reportId = (String) zxvoJson.getResp(); // not null
                    } catch (Exception e) {
                        throw new BizException("调用征信系统异常", e);
                    }
                    log.info("征信单笔查询接口调用完成,流水号:" + appNo + "，报告编号：" + reportId);
                }else {//大于当前时间，不进行落库
                    reportId = zxInfo.get(0).getReportId();
                    log.info("征信报告时间未到，不查询征信:" + appNo + "，报告编号：" + reportId);
                }
            }else {//无征信报告，调用征信接口
                try {
                    ZXVO zxvoJson = zxCXA01Service.Zxservice(ZXQueryReports,params);
                    reportId = (String) zxvoJson.getResp(); // not null
                } catch (Exception e) {
                    throw new BizException("调用征信系统异常", e);
                }
                log.info("征信单笔查询接口调用完成,流水号:" + appNo + "，报告编号：" + reportId);
            }

            /** 查询规则过程表信息 */
            NlsProcessRuleVO nlsProcessRuleVO = new NlsProcessRuleVO();
            nlsProcessRuleVO.setApplySeq(applySeq);
            nlsProcessRuleVO = nlsProcessRuleService.queryByPk(nlsProcessRuleVO);
            /** 添加要执行的规则 */
            List<PrdSoltRuleVO> prdSoltRules = prdSoltRuleService.queryByPrdIdAndSoltCode(nlsApplyInfoVO.getPrdCode(), slotCode);
            //规则14： 判断客户是否有征信数据
            int whiteCus = 0;
            if(reportId == null || "".equals(reportId)) {
                whiteCus = 1;
            }

            int acctCntSum = 0;//各账户类型的账户数合计总数
            int overdueNum = 0;//统计贷款逾期次数
            int ccAbnormalNum = 0;//统计贷记卡异常次数
            int sccAbnormalNum = 0;//统计准贷记卡异常次数
            int loanOverdue12MContNum = 0;//最近12月连续逾期贷款次数
            int loanOverdue12MTotalNum = 0;//最近12月累计逾期贷款次数
            int ccOverdue12MContNum = 0;//最近12月贷记卡账户连续逾期次数
            int ccOverdue12MTotalNum = 0;//最近12月贷记卡账户累计逾期次数
            int scOverdue12MContNum = 0;//最近12月准贷记卡账户连续逾期次数
            int scOverdue12MTotalNum = 0;//最近12月准贷记卡账户累计逾期次数
            int od180DaysUnpydBalSum = 0;//统计准贷记卡有透支180天以上未未付余额笔数
            int loanSpecFlag = 0;//特殊交易标识
            int loan5Sum = 0;//统计出现五级分类
            int aprvlQryTmsSum = 0;//最近一个月合计查询次数(贷款申请+信用卡申请)

            ZXJsonInfoVO queryByReportVo = new ZXJsonInfoVO();
            queryByReportVo.setReportId(reportId);
            List<ZXJsonInfoVO> zxInfoList = zxJsonInfoService.queryByReportId(queryByReportVo);
            if (zxInfoList.size()>0){
                //马上二代征信json报文内容
                String json_content = zxInfoList.get(0).getJsonContent();
                JSONObject jsonObj = JSONObject.parseObject(json_content);
                int nonRvlvngCrAcctCnt = 0;
                int rvlvmnLmtAcctCnt = 0;
                int rvlvngCrAcctCnt = 0;
                int crCardAcctCnt = 0;
                int qscrdtAcctCnt = 0;
                int acctcntTot = 0;
                //非循环贷款账户数
                JSONObject nonRvlvngCrAcctSmzgInfStructObj = JSONObject.parseObject(jsonObj.getString("NonRvlvngCrAcctSmzgInfStruct"));
                if(nonRvlvngCrAcctSmzgInfStructObj != null){
                    if (nonRvlvngCrAcctSmzgInfStructObj.getString("NonRvlvngCrAcctCnt") != null && !"".equals(nonRvlvngCrAcctSmzgInfStructObj.getString("NonRvlvngCrAcctCnt"))){
                        nonRvlvngCrAcctCnt = Integer.valueOf(nonRvlvngCrAcctSmzgInfStructObj.getString("NonRvlvngCrAcctCnt")).intValue();
                    }
                }
                //循环额度账户数
                JSONObject rvlvmnLmtDwCentAcctSmzgInfStructObj = JSONObject.parseObject(jsonObj.getString("RvlvmnLmtDwCentAcctSmzgInfStruct"));
                if(rvlvmnLmtDwCentAcctSmzgInfStructObj != null){
                    if (rvlvmnLmtDwCentAcctSmzgInfStructObj.getString("RvlvmnLmtAcctCnt") != null && !"".equals(rvlvmnLmtDwCentAcctSmzgInfStructObj.getString("RvlvmnLmtAcctCnt"))){
                        rvlvmnLmtAcctCnt = Integer.valueOf(rvlvmnLmtDwCentAcctSmzgInfStructObj.getString("RvlvmnLmtAcctCnt")).intValue();
                    }
                }
                //循环贷账户数
                JSONObject rvlvngCrAcctSmzgInfStructObj = JSONObject.parseObject(jsonObj.getString("RvlvngCrAcctSmzgInfStruct"));
                if(rvlvngCrAcctSmzgInfStructObj != null){
                    if (rvlvngCrAcctSmzgInfStructObj.getString("RvlvngCrAcctCnt") != null && !"".equals(rvlvngCrAcctSmzgInfStructObj.getString("RvlvngCrAcctCnt"))){
                        rvlvngCrAcctCnt = Integer.valueOf(rvlvngCrAcctSmzgInfStructObj.getString("RvlvngCrAcctCnt")).intValue();
                    }
                }
                //贷记卡账户数
                JSONObject crCardAcctSmzgInfStructObj = JSONObject.parseObject(jsonObj.getString("CrCardAcctSmzgInfStruct"));
                if(crCardAcctSmzgInfStructObj != null){
                    if (crCardAcctSmzgInfStructObj.getString("CrCardAcctCnt") != null && !"".equals(crCardAcctSmzgInfStructObj.getString("CrCardAcctCnt"))){
                        crCardAcctCnt = Integer.valueOf(crCardAcctSmzgInfStructObj.getString("CrCardAcctCnt")).intValue();
                    }
                }
                //未销户准贷记卡账户数
                JSONObject qscrdtAcctSmzgInfStructObj = JSONObject.parseObject(jsonObj.getString("QscrdtAcctSmzgInfStruct"));
                if(qscrdtAcctSmzgInfStructObj != null){
                    if (qscrdtAcctSmzgInfStructObj.getString("QscrdtAcctCnt") != null && !"".equals(qscrdtAcctSmzgInfStructObj.getString("QscrdtAcctCnt"))){
                        qscrdtAcctCnt = Integer.valueOf(qscrdtAcctSmzgInfStructObj.getString("QscrdtAcctCnt")).intValue();
                    }
                }
                //信贷交易提示信息的账户数合计
                JSONObject crdtTxnSugstInfStructObj = JSONObject.parseObject(jsonObj.getString("CrdtTxnSugstInfStruct"));
                if (Objects.nonNull(crdtTxnSugstInfStructObj)){
                    if (!StringUtil.isNullorBank(crdtTxnSugstInfStructObj.getString("AcctCntTot"))){
                        acctcntTot = Integer.valueOf(crdtTxnSugstInfStructObj.getString("AcctCntTot")).intValue();
                    }
                }

                //规则15：客户个人征信报告无任何贷款、贷记卡及准贷记卡记录(acctCntSum < 1)
                acctCntSum = nonRvlvngCrAcctCnt + rvlvmnLmtAcctCnt + rvlvngCrAcctCnt + crCardAcctCnt + qscrdtAcctCnt + acctcntTot;
                log.info("征信规则参数准备，客户各账户类型的账户总数： " + acctCntSum);

                JSONArray dbOrCrAcctInfArry = JSONArray.parseArray(jsonObj.getString("DbOrCrAcctInfArry"));//借贷账户信息数组
                String acctTp = "";//账户类型
                String acctSt = "";//最新表现状态
                String loan5Clsf = "";//最新表现贷款五级分类
                String loan5Clsf1 = "";//最近一次月份表现贷款五级分类
                int crnOdueTrmCnt = 0;//最近一次月份当前逾期期数
                String spclTxnTp = "";//特殊交易类型
                double od180DaysUnpydBal = 0.00;
                String loan5[] = {"3","4","5"};//五级分类状态数组:1正常 2关注 3次级 4可疑 5损失 6违约 9未分类
                List<String> list = Arrays.asList(loan5);
                String cloan5[] = {"2","3","4","5","6","9"};//用于判断最新表现中的五级分类
                List<String> cloan5List = Arrays.asList(cloan5);
                String spclType[] = {"2","3","8"};//特殊交易类型数组:1展期 2担保人（第三方）代偿 3以资抵债 4提前还款(包括提前归还部分本金、还款期限不变，以及缩短还款期限两种情况) 5提前结清 6强制平仓，未结清 7强制平仓，已结清 8司法追偿 9其他 11债务减免 12资产剥离13资产转让 14信用卡个性化分期 16银行主动延期 17强制平仓
                List<String> listTs = Arrays.asList(spclType);
                String status1[] = {"1","2","3","4","5","6","7"};//还款状态1-7数组
                List<String> listSt1 = Arrays.asList(status1);
                String status3[] = {"3","4","5","6","7"};//还款状态3-7数组
                List<String> listSt3 = Arrays.asList(status3);
                int spclTypeCount = 0;//统计出现特殊交易类型
                String rctly24MosSpfMnth = "";//最近24个月具体月份
                String rpymtSt1 = "";//最近24个月具体月份对应的还款状态
                String[] months24;//最近24个月数组
                String[] months12 = new String[12];//最近12个月数组
                int loanOverdue12MTotalNumTemp = 0;//单笔贷款累计逾期6次及以上
                int ccOverdue12MTotalNumTemp = 0;//单张贷记卡累计逾期6次及以上
                int scOverdue12MTotalNumTemp = 0;//单张准贷记卡累计逾期6次及以上

                if(dbOrCrAcctInfArry != null && dbOrCrAcctInfArry.size()>0){
                    for (int i = 0;i < dbOrCrAcctInfArry.size();i++){//借贷账户信息数组遍历start
                        loan5Clsf = "";//重置最新表现的五级分类
                        loan5Clsf1 = "";//重置最近一次月份的五级分类
                        od180DaysUnpydBal = 0.00;//重置最近一次月份表现透支180天以上未付余额
                        crnOdueTrmCnt = 0;//重置最近一次月份当前逾期期数，用于统计下一个账户
                        loanOverdue12MTotalNumTemp = 0;//重置每笔贷款累计逾期次数，用于统计下一笔贷款
                        ccOverdue12MTotalNumTemp = 0;//重置每张贷记卡累计逾期次数，用于统计下一张贷记卡
                        scOverdue12MTotalNumTemp = 0;//重置每张准贷记卡累计逾期次数，用于统计下一张准贷记卡

                        JSONObject dbOrCrAcctInfObj = dbOrCrAcctInfArry.getJSONObject(i);
                        JSONObject bscInfStructObj = JSONObject.parseObject(dbOrCrAcctInfObj.getString("BscInfStruct"));//基本信息
                        JSONObject nwstPerfmcInfStructObj = JSONObject.parseObject(dbOrCrAcctInfObj.getString("NwstPerfmcInfStruct"));//最新表现信息
                        JSONObject rctlyOnceMnthPerfmcInfStructObj = JSONObject.parseObject(dbOrCrAcctInfObj.getString("RctlyOnceMnthPerfmcInfStruct"));//最近一次月份表现信息
                        if(bscInfStructObj != null){
                            acctTp = bscInfStructObj.getString("AcctTp");
                        }
                        if(nwstPerfmcInfStructObj != null){
                            acctSt = nwstPerfmcInfStructObj.getString("AcctSt");
                            loan5Clsf = nwstPerfmcInfStructObj.getString("Loan5Clsf");
                        }
                        if(rctlyOnceMnthPerfmcInfStructObj != null){
                            loan5Clsf1 = rctlyOnceMnthPerfmcInfStructObj.getString("Loan5Clsf1");
                            if (rctlyOnceMnthPerfmcInfStructObj.getString("Od180DaysUnpydBal") != null && !"".equals(rctlyOnceMnthPerfmcInfStructObj.getString("Od180DaysUnpydBal"))){
                                od180DaysUnpydBal = Double.parseDouble(rctlyOnceMnthPerfmcInfStructObj.getString("Od180DaysUnpydBal"));//最近一次月份表现透支180天以上未付余额
                            }
                            if (rctlyOnceMnthPerfmcInfStructObj.getString("CrnOdueTrmCnt") != null && !"".equals(rctlyOnceMnthPerfmcInfStructObj.getString("CrnOdueTrmCnt"))){
                                crnOdueTrmCnt = Integer.valueOf(rctlyOnceMnthPerfmcInfStructObj.getString("CrnOdueTrmCnt")).intValue();
                            }
                        }
                        JSONArray rpymtStInfArry = JSONObject.parseArray(dbOrCrAcctInfObj.getString("RpymtStInfArry"));//还款状态信息数组
                        if(rpymtStInfArry !=null && rpymtStInfArry.size() > 0){
                            months24 = new String[rpymtStInfArry.size()];//根据实际返回数组信息创建
                            for (int h = 0;h < rpymtStInfArry.size();h++){
                                JSONObject  rpymtStInfObj = rpymtStInfArry.getJSONObject(h);
                                months24[h] = rpymtStInfObj.getString("Rctly24MosSpfMnth");//抽取具体月份数组
                            }
                            Arrays.sort(months24);//具体月份排序
                            if (rpymtStInfArry.size() <= 12){
                                months12 = Arrays.copyOfRange(months24,0,rpymtStInfArry.size());
                            }else {//超过12个月份，截取最近12个月份
                                months12 = Arrays.copyOfRange(months24,rpymtStInfArry.size()-12,rpymtStInfArry.size());//复制最近的12个月
                            }
                            for (int u = 0;u < rpymtStInfArry.size();u++){//还款状态信息数组遍历start
                                JSONObject rpymtStInfObj2 = rpymtStInfArry.getJSONObject(u);
                                rctly24MosSpfMnth = rpymtStInfObj2.getString("Rctly24MosSpfMnth");
                                rpymtSt1 = rpymtStInfObj2.getString("RpymtSt1");
                                if (acctTp != null) {
                                    //规则4：最近12月连续逾期贷款次数
                                    if ((acctTp.equals(AccountTypeEnum.NONRVLVNGCRACCT.getCode()) || acctTp.equals(AccountTypeEnum.RVLVNGCRACCT.getCode()) || acctTp.equals(AccountTypeEnum.RVLVMNLMTACCT.getCode()))
                                            && Arrays.asList(months12).contains(rctly24MosSpfMnth) && !"".equals(rpymtSt1) && rpymtSt1 != null && listSt3.contains(rpymtSt1)) {
                                        loanOverdue12MContNum++;
                                    }
                                    //规则5：最近12月累计逾期贷款次数
                                    if ((acctTp.equals(AccountTypeEnum.NONRVLVNGCRACCT.getCode()) || acctTp.equals(AccountTypeEnum.RVLVNGCRACCT.getCode()) || acctTp.equals(AccountTypeEnum.RVLVMNLMTACCT.getCode()))
                                            && Arrays.asList(months12).contains(rctly24MosSpfMnth) && !"".equals(rpymtSt1) && rpymtSt1 != null && listSt1.contains(rpymtSt1)) {
//                                        loanOverdue12MTotalNum++;
                                        loanOverdue12MTotalNumTemp++;
                                    }
                                    //规则6：最近12月贷记卡账户连续逾期次数
                                    if (acctTp.equals(AccountTypeEnum.CRCARDACCT.getCode()) && Arrays.asList(months12).contains(rctly24MosSpfMnth) && !"".equals(rpymtSt1) && rpymtSt1 != null && listSt3.contains(rpymtSt1)) {
                                        ccOverdue12MContNum++;
                                    }
                                    //规则7：最近12月贷记卡账户累计逾期次数
                                    if (acctTp.equals(AccountTypeEnum.CRCARDACCT.getCode()) && Arrays.asList(months12).contains(rctly24MosSpfMnth) && !"".equals(rpymtSt1) && rpymtSt1 != null && listSt1.contains(rpymtSt1)) {
//                                        ccOverdue12MTotalNum++;
                                        ccOverdue12MTotalNumTemp++;
                                    }
                                    //规则8：最近12月准贷记卡账户连续逾期次数
                                    if (acctTp.equals(AccountTypeEnum.QSCRDTACCT.getCode()) && Arrays.asList(months12).contains(rctly24MosSpfMnth) && !"".equals(rpymtSt1) && rpymtSt1 != null && listSt3.contains(rpymtSt1)) {
                                        scOverdue12MContNum++;
                                    }
                                    //规则9：最近12月准贷记卡账户累计逾期次数
                                    if (acctTp.equals(AccountTypeEnum.QSCRDTACCT.getCode()) && Arrays.asList(months12).contains(rctly24MosSpfMnth) && !"".equals(rpymtSt1) && rpymtSt1 != null && listSt1.contains(rpymtSt1)) {
//                                        scOverdue12MTotalNum++;
                                        scOverdue12MTotalNumTemp++;
                                    }
                                }
                            }//还款状态信息数组遍历end
                            if (loanOverdue12MTotalNumTemp >= 6){//单笔贷款累计逾期6次及以上
                                loanOverdue12MTotalNum += loanOverdue12MTotalNumTemp;//所有符合条件的贷款逾期次数汇总
                            }
                            if (ccOverdue12MTotalNumTemp >= 6){//单张贷记卡累计逾期6次及以上
                                ccOverdue12MTotalNum += ccOverdue12MTotalNumTemp;//所有符合条件的贷记卡逾期次数汇总
                            }
                            if (scOverdue12MTotalNumTemp >= 6){//单张准贷记卡累计逾期6次及以上
                                scOverdue12MTotalNum += scOverdue12MTotalNumTemp;//所有符合条件的准贷记卡逾期次数汇总
                            }
                        }

                        JSONArray spclTxnInfArry = JSONObject.parseArray(dbOrCrAcctInfObj.getString("SpclTxnInfArry"));//特殊交易类型信息数组
                        if (spclTxnInfArry != null && spclTxnInfArry.size()>0){
                            for (int k = 0;k < spclTxnInfArry.size();k++){
                                JSONObject spclTxnInfObj = spclTxnInfArry.getJSONObject(k);
                                spclTxnTp = spclTxnInfObj.getString("SpclTxnTp");
                                if (listTs.contains(spclTxnTp)){
                                    spclTypeCount++;
                                }
                            }
                        }

                        if (acctTp != null) {
                            if (acctSt != null) {
                                //规则1：贷款逾期次数
                                if (acctTp.equals(AccountTypeEnum.NONRVLVNGCRACCT.getCode()) && (acctSt.equals(AcctStEnum.D1_2.getCode()) || acctSt.equals(AcctStEnum.D1_4.getCode()) || acctSt.equals(AcctStEnum.D1_6.getCode())
                                        || acctSt.equals(AcctStEnum.D1_7.getCode()) || acctSt.equals(AcctStEnum.D1_8.getCode()) || cloan5List.contains(loan5Clsf) || crnOdueTrmCnt > 0)) {
                                    overdueNum++;
                                } else if (acctTp.equals(AccountTypeEnum.RVLVNGCRACCT.getCode()) && (acctSt.equals(AcctStEnum.R1_2.getCode()) || acctSt.equals(AcctStEnum.R1_4.getCode()) || acctSt.equals(AcctStEnum.R1_5.getCode())
                                        || acctSt.equals(AcctStEnum.R1_6.getCode()) || acctSt.equals(AcctStEnum.R1_8.getCode()) || cloan5List.contains(loan5Clsf) || crnOdueTrmCnt > 0)) {
                                    overdueNum++;
                                } else if (acctTp.equals(AccountTypeEnum.RVLVMNLMTACCT.getCode()) && (acctSt.equals(AcctStEnum.R4_2.getCode()) || acctSt.equals(AcctStEnum.R4_4.getCode()) || acctSt.equals(AcctStEnum.R4_6.getCode())
                                        || acctSt.equals(AcctStEnum.R4_8.getCode()) || cloan5List.contains(loan5Clsf) || crnOdueTrmCnt > 0)) {
                                    overdueNum++;
                                }
                                log.info("征信规则参数准备，贷款当前状态为“逾期”的总数为： " + overdueNum);
                                //规则2：贷记卡异常次数
                                if ((acctTp.equals(AccountTypeEnum.CRCARDACCT.getCode()) && (acctSt.equals(AcctStEnum.R2andR3_2.getCode()) || acctSt.equals(AcctStEnum.R2andR3_3.getCode()) || acctSt.equals(AcctStEnum.R2andR3_31.getCode()) || acctSt.equals(AcctStEnum.R2andR3_5.getCode()) || acctSt.equals(AcctStEnum.R2andR3_8.getCode()) || cloan5List.contains(loan5Clsf)))
                                        || (acctTp.equals(AccountTypeEnum.CRCARDACCT.getCode()) && crnOdueTrmCnt > 0)) {
                                    ccAbnormalNum++;
                                }
                                log.info("征信规则参数准备，贷款卡异常总数为： " + ccAbnormalNum);
                                //规则3：准贷记卡异常次数
                                if ((acctTp.equals(AccountTypeEnum.QSCRDTACCT.getCode()) && (acctSt.equals(AcctStEnum.R2andR3_2.getCode()) || acctSt.equals(AcctStEnum.R2andR3_3.getCode()) || acctSt.equals(AcctStEnum.R2andR3_31.getCode()) || acctSt.equals(AcctStEnum.R2andR3_5.getCode()) || acctSt.equals(AcctStEnum.R2andR3_8.getCode()) || cloan5List.contains(loan5Clsf)))
                                        || (acctTp.equals(AccountTypeEnum.QSCRDTACCT.getCode()) && crnOdueTrmCnt > 0)) {
                                    sccAbnormalNum++;
                                } else if (acctTp.equals(AccountTypeEnum.COLLECTIONACCT.getCode()) && acctSt.equals(AcctStEnum.C1_1.getCode())) {
                                    sccAbnormalNum++;
                                }
                                log.info("征信规则参数准备，准贷款卡异常总数为： " + sccAbnormalNum);
                            }
                            //规则11：账户类型：D1\R1\R4 且“最新表现信息段”中五级分类为次级、可疑、损失其一或者最近一次月度表现账户状态中五级分类为次级、可疑、损失其一
                            if ((acctTp.equals(AccountTypeEnum.NONRVLVNGCRACCT.getCode()) || acctTp.equals(AccountTypeEnum.RVLVNGCRACCT.getCode()) || acctTp.equals(AccountTypeEnum.RVLVMNLMTACCT.getCode()))
                                    && (list.contains(loan5Clsf) || list.contains(loan5Clsf1))) {
                                loan5Sum++;
                            }
                            log.info("征信规则参数准备，五级分类总数为： " + loan5Sum);
                            //规则12：任一笔准贷记卡有透支180天以上未未付余额
                            if (acctTp.equals(AccountTypeEnum.QSCRDTACCT.getCode()) && od180DaysUnpydBal > 0) {
                                od180DaysUnpydBalSum++;
                            }
                            log.info("征信规则参数准备，准贷记卡有透支180天以上未支付余额为： " + od180DaysUnpydBalSum);
                        }
                    }//借贷账户信息数组遍历end
                }

                String beRecovBsnTp = "";//被追偿业务类型
                int beRecovAcctCnt = 0;//被追偿账户数
                int zcCount = 0;//资产处置业务账户数
                int dkCount = 0;//垫款业务账户数
                int bdDbtSmzgAcctCnt = 0;//呆账账户数

                JSONObject bdDbtSmzgInfStructObj = JSONObject.parseObject(jsonObj.getString("BdDbtSmzgInfStruct"));
                if(bdDbtSmzgInfStructObj != null){
                    if (bdDbtSmzgInfStructObj.getString("BdDbtSmzgAcctCnt") != null && !"".equals(bdDbtSmzgInfStructObj.getString("BdDbtSmzgAcctCnt"))){
                        bdDbtSmzgAcctCnt = Integer.valueOf(bdDbtSmzgInfStructObj.getString("BdDbtSmzgAcctCnt")).intValue();
                    }
                }
                JSONObject beRecovSmzgInfStructObj = JSONObject.parseObject(jsonObj.getString("BeRecovSmzgInfStruct"));
                if(beRecovSmzgInfStructObj != null){
                    JSONArray beRecovSmzgInfArry = JSONArray.parseArray(beRecovSmzgInfStructObj.getString("BeRecovSmzgInfArry"));
                    if(beRecovSmzgInfArry != null && beRecovSmzgInfArry.size()>0){
                        for (int h = 0;h < beRecovSmzgInfArry.size();h++){
                            JSONObject beRecovSmzgInfObj = beRecovSmzgInfArry.getJSONObject(h);
                            beRecovBsnTp = beRecovSmzgInfObj.getString("BeRecovBsnTp");
                            if (beRecovSmzgInfObj.getString("BeRecovAcctCnt") != null && !"".equals(beRecovSmzgInfObj.getString("BeRecovAcctCnt"))){
                                beRecovAcctCnt = Integer.valueOf(beRecovSmzgInfObj.getString("BeRecovAcctCnt")).intValue();
                                if (beRecovBsnTp.equals("1") && beRecovAcctCnt > 0) {
                                    zcCount = beRecovAcctCnt;
                                }else if (beRecovBsnTp.equals("2") && beRecovAcctCnt > 0) {
                                    dkCount = beRecovAcctCnt;
                                }
                            }
                        }
                    }
                }
                //规则10：贷款出现“呆账”、“资产处置”、“垫款”等特殊情况 或者 任一笔贷款的“特殊交易类型”为“以资抵债”、“担保人（第三方）代偿”、“司法追偿”等特殊情形。
                if (bdDbtSmzgAcctCnt >= 1 || zcCount >= 1 || dkCount >= 1 || spclTypeCount > 0){
                    loanSpecFlag = 1;
                }else {
                    loanSpecFlag = 0;
                }

                int rctly1MosLoanAprvlQryTms = 0;//最近1个月贷款审批查询次数
                int rctly1MosCrCardAprvlQryTms = 0;//最近1个月信用卡审批查询次数
                JSONObject qryRcrdSmzgInfStructObj = JSONObject.parseObject(jsonObj.getString("QryRcrdSmzgInfStruct"));//查询记录汇总信息
                if (qryRcrdSmzgInfStructObj.getString("Rctly1MosLoanAprvlQryTms") != null && !"".equals(qryRcrdSmzgInfStructObj.getString("Rctly1MosLoanAprvlQryTms"))){
                    rctly1MosLoanAprvlQryTms = Integer.valueOf(qryRcrdSmzgInfStructObj.getString("Rctly1MosLoanAprvlQryTms")).intValue();
                }
                if (qryRcrdSmzgInfStructObj.getString("Rctly1MosCrCardAprvlQryTms") != null && !"".equals(qryRcrdSmzgInfStructObj.getString("Rctly1MosCrCardAprvlQryTms"))){
                    rctly1MosCrCardAprvlQryTms = Integer.valueOf(qryRcrdSmzgInfStructObj.getString("Rctly1MosCrCardAprvlQryTms")).intValue();
                }

                //规则13：最近一个月合计查询次数(aprvlQryTmsSum>=10 则拒绝)
                aprvlQryTmsSum = rctly1MosLoanAprvlQryTms + rctly1MosCrCardAprvlQryTms;
                log.info("征信规则参数准备，贷款申请和信用卡申请的总数为： " + aprvlQryTmsSum);
            }

            /** 执行规则 **/
            ReqRuleVo reqRuleVo = new ReqRuleVo();
            reqRuleVo.setAppNo(appNo);
            reqRuleVo.setPrdCode(nlsApplyInfoVO.getPrdCode());
            ReqMsZxRuleVo param = new ReqMsZxRuleVo();
            param.setMsAcctCntSum(acctCntSum);
            param.setMsOverdueNum(overdueNum);
            param.setMsCcAbnormalNum(ccAbnormalNum);
            param.setMsSccAbnormalNum(sccAbnormalNum);
            param.setMsCcOverdue12MContNum(ccOverdue12MContNum);
            param.setMsCcOverdue12MTotalNum(ccOverdue12MTotalNum);
            param.setMsLoanOverdue12MContNum(loanOverdue12MContNum);
            param.setMsLoanOverdue12MTotalNum(loanOverdue12MTotalNum);
            param.setMsScOverdue12MContNum(scOverdue12MContNum);
            param.setMsScOverdue12MTotalNum(scOverdue12MTotalNum);
            param.setMsLoanSpecFlag(loanSpecFlag);
            param.setMsLoan5Sum(loan5Sum);
            param.setMsOd180DaysUnpydBalSum(od180DaysUnpydBalSum);
            param.setMsAprvlQryTmsSum(aprvlQryTmsSum);
            param.setWhiteCus(whiteCus);
            reqRuleVo.setReqMsZxRuleVo(param);

            /** 批量执行规则 **/
            List<RespRuleVO> ruleList = ruleService.executeBatchRule(Rule.RuleType.MSZX, reqRuleVo);
            /** 规则结果分组 **/
            Map<String, List<RespRuleVO>> map = ruleList.stream().collect(Collectors.groupingBy(RespRuleVO::getRuleId));
            /** 规则结果信息  反馈给开放平台*/
            String refuseMsg = "";
            /** 规则结果信息  记录拒绝原因细类*/
            StringBuilder sb = new StringBuilder();

            for (int j = 0; j < prdSoltRules.size(); j++) {
                String order = prdSoltRules.get(j).getRuleOrder();
                /** 规则名称method映射 */
                Method methodRuleName = NlsProcessRuleVO.class.getMethod("setRuleName" + order, String.class);
                /** 规则状态method映射 */
                Method methodRuleState = NlsProcessRuleVO.class.getMethod("setRuleState" + order, String.class);
                /** 规则时间method映射 */
                Method methodRuleTime = NlsProcessRuleVO.class.getMethod("setRuleTime" + order, String.class);

                methodRuleName.invoke(nlsProcessRuleVO, prdSoltRules.get(j).getRuleCode());
                methodRuleTime.invoke(nlsProcessRuleVO, DateUtility.getCurrAppDateTimeString());
                if (map.get(prdSoltRules.get(j).getRuleCode()) != null) {
                    methodRuleState.invoke(nlsProcessRuleVO, PrdAdaptedSoltEnums.SoltProcessStateEnum.FAILURE.getCode());
                    sb.append(prdSoltRules.get(j).getRuleName()).append("规则不通过;");
                    /**根据规则id映射返回开放平台错误信息**/
                    refuseMsg = Rule.parseWithRuleId(prdSoltRules.get(j).getRuleCode()).getMsg();
                } else {
                    methodRuleState.invoke(nlsProcessRuleVO, PrdAdaptedSoltEnums.SoltProcessStateEnum.SUCCESS.getCode());
                }
            }
            nlsProcessBizVo.setRefuseMsg(refuseMsg);
            /** 插入规则过程表 */
            nlsProcessRuleService.updateByPk(nlsProcessRuleVO);

            if (!ruleList.isEmpty()) {
                throw new BizException(sb.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(Arrays.toString(e.getStackTrace()));
            nlsProcessBizVo.setExceptionFlag(true);
            nlsProcessBizVo.setExceptionMsg(e);
        }
    }

}
